#include "pcagent_command_line_validator.h"
#include "extra_args_parser.h"
#include "const_cmd_line.h"
#include "../base/command_line_validator.h"
#include "../base/command_line_parser.h"
#include "../base/debug.h"
#include "../base/error.h"
#include "../base/logging.h"

PCAgentCommandLineValidator::PCAgentCommandLineValidator()
{
}

PCAgentCommandLineValidator::~PCAgentCommandLineValidator()
{
}

HRESULT PCAgentCommandLineValidator::Setup()
{
	validator_.reset(new CommandLineValidator);

	CString cmd_line;

	cmd_line.Empty();
	CreateScenario(cmd_line, &PCAgentCommandLineValidator::OnNoArgs);

	// pcagent.exe /svc
	cmd_line.Format(_T("/%s"), kCmdLineService);
	CreateScenario(cmd_line, &PCAgentCommandLineValidator::OnService);

	// pcagent.exe /regserver
	cmd_line.Format(_T("/%s"), kCmdRegServer);
	CreateScenario(cmd_line, &PCAgentCommandLineValidator::OnRegServer);

	// pcagent.exe /unregserver
	cmd_line.Format(_T("/%s"), kCmdUnregServer);
	CreateScenario(cmd_line, &PCAgentCommandLineValidator::OnUnregServer);

	// pcagent.exe -Embedding. The -Embedding text is injected via COM.
	CreateScenario(kCmdLineComServerDash,
		&PCAgentCommandLineValidator::OnComServer);

	return S_OK;
}

HRESULT PCAgentCommandLineValidator::Validate(const CommandLineParser* parser,
										   CommandLineArgs* args)
{
	ASSERT1(parser);
	ASSERT1(args);

	parser_ = parser;
	args_ = args;

	CString scenario_name;
	HRESULT hr = validator_->Validate(*parser_, &scenario_name);
	if (FAILED(hr))
	{
		CORE_LOG(LE, (_T("[GoopdateCommandLineValidator::Validate Failed][0x%x]"), hr));
		return hr;
	}

	MapScenarioHandlersIter iter = scenario_handlers_.find(scenario_name);
	if (iter == scenario_handlers_.end())
	{
		ASSERT1(false);
		return PCAGENT_COMMANDLINE_E_NO_SCENARIO_HANDLER;
	}

	ScenarioHandler handler = (*iter).second;
	return (this->*handler)();
}

void PCAgentCommandLineValidator::CreateScenario(const TCHAR* cmd_line, 
												 ScenarioHandler handler)
{
	// Prepend the program name onto the cmd_line.
	CString scenario_cmd_line;
	scenario_cmd_line.Format(_T("prog.exe %s"), cmd_line);

	CString scenario_name;
	validator_->CreateScenarioFromCmdLine(scenario_cmd_line, &scenario_name);
	scenario_handlers_[scenario_name] = handler;
}

HRESULT PCAgentCommandLineValidator::GetExtraAndAppArgs(
	const CString& switch_name)
{
	HRESULT hr = parser_->GetSwitchArgumentValue(switch_name, 0, 
		&args_->extra_args_str);
	if (FAILED(hr)) return hr;

	hr = parser_->GetSwitchArgumentValue(kCmdLineAppArgs, 0, 
		&args_->app_args_str);
	if (FAILED(hr))
		args_->app_args_str.Empty();

	ExtraArgsParser extra_args_parser;
	return extra_args_parser.Parse(args_->extra_args_str, args_->app_args_str,
		&args_->extra);
}

HRESULT PCAgentCommandLineValidator::OnNoArgs()
{
	args_->mode = COMMANDLINE_MODE_NOARGS;
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnCore()
{
	args_->mode = COMMANDLINE_MODE_CORE;
	args_->is_crash_handler_disabled = parser_->HasSwitch(kCmdLineNoCrashHandler);

	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnCrashHandler()
{
// 	args_->mode = COMMANDLINE_MODE_CRASH_HANDLER;
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnService() {
	args_->mode = COMMANDLINE_MODE_SERVICE;
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnMediumService()
{
// 	args_->mode = COMMANDLINE_MODE_MEDIUM_SERVICE;
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnServiceRegister()
{
// 	args_->mode = COMMANDLINE_MODE_SERVICE_REGISTER;
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnServiceUnregister()
{
// 	args_->mode = COMMANDLINE_MODE_SERVICE_UNREGISTER;
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnRegServer()
{
	args_->mode = COMMANDLINE_MODE_REGSERVER;
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnUnregServer()
{
	args_->mode = COMMANDLINE_MODE_UNREGSERVER;
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnNetDiags()
{
	args_->mode = COMMANDLINE_MODE_NETDIAGS;
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnCrash()
{
	args_->mode = COMMANDLINE_MODE_CRASH;
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnComServer()
{
	args_->mode = COMMANDLINE_MODE_COMSERVER;
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnComBroker()
{
// 	args_->mode = COMMANDLINE_MODE_COMBROKER;
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnDemand() {
// 	args_->mode = COMMANDLINE_MODE_ONDEMAND;
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnInstall()
{
	args_->mode = COMMANDLINE_MODE_INSTALL;
	parser_->GetSwitchArgumentValue(kCmdLineInstallSource,
		0,
		&args_->install_source);
	parser_->GetSwitchArgumentValue(kCmdLineSessionId,
		0,
		&args_->session_id);
	args_->is_silent_set = parser_->HasSwitch(kCmdLineSilent);
	args_->is_eula_required_set = parser_->HasSwitch(kCmdLineEulaRequired);
	args_->is_oem_set = parser_->HasSwitch(kCmdLineOem);
	args_->is_install_elevated = parser_->HasSwitch(kCmdLineInstallElevated);
	return GetExtraAndAppArgs(kCmdLineInstall);
}

HRESULT PCAgentCommandLineValidator::OnUpdate()
{
	args_->mode = COMMANDLINE_MODE_UPDATE;
	parser_->GetSwitchArgumentValue(kCmdLineSessionId,
		0,
		&args_->session_id);
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnInstallHandoffWorker()
{
// 	args_->mode = COMMANDLINE_MODE_HANDOFF_INSTALL;
// 	parser_->GetSwitchArgumentValue(kCmdLineInstallSource,
// 		0,
// 		&args_->install_source);
// 	parser_->GetSwitchArgumentValue(kCmdLineSessionId,
// 		0,
// 		&args_->session_id);
// 	args_->is_silent_set = parser_->HasSwitch(kCmdLineSilent);
// 	args_->is_eula_required_set = parser_->HasSwitch(kCmdLineEulaRequired);
// 	args_->is_offline_set = parser_->HasSwitch(kCmdLineLegacyOfflineInstall) ||
// 		parser_->HasSwitch(kCmdLineOfflineDir);
// 
// 	if (SUCCEEDED(parser_->GetSwitchArgumentValue(kCmdLineOfflineDir,
// 		0,
// 		&args_->offline_dir))) {
// 			RemoveMismatchedEndQuoteInDirectoryPath(&args_->offline_dir);
// 			::PathRemoveBackslash(CStrBuf(args_->offline_dir, MAX_PATH));
// 	}
// 
	return GetExtraAndAppArgs(kCmdLineAppHandoffInstall);
}

HRESULT PCAgentCommandLineValidator::OnUpdateApps()
{
// 	args_->mode = COMMANDLINE_MODE_UA;
	args_->is_machine_set = parser_->HasSwitch(kCmdLineMachine);
	parser_->GetSwitchArgumentValue(kCmdLineInstallSource,
		0,
		&args_->install_source);
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnReportCrash()
{
	args_->mode = COMMANDLINE_MODE_REPORTCRASH;
	args_->is_machine_set = parser_->HasSwitch(kCmdLineMachine);
	parser_->GetSwitchArgumentValue(kCmdLineCustomInfoFileName,
		0,
		&args_->custom_info_filename);
	return parser_->GetSwitchArgumentValue(kCmdLineReport,
		0,
		&args_->crash_filename);
}

HRESULT PCAgentCommandLineValidator::OnReportCrashInteractive()
{
	args_->mode = COMMANDLINE_MODE_REPORTCRASH;
	args_->is_interactive_set = true;
	args_->is_machine_set = parser_->HasSwitch(kCmdLineMachine);
	return parser_->GetSwitchArgumentValue(kCmdLineInteractive,
		0,
		&args_->crash_filename);
}

HRESULT PCAgentCommandLineValidator::OnWebPlugin()
{
// 	HRESULT hr = parser_->GetSwitchArgumentValue(kCmdLineInstallSource,
// 		0,
// 		&args_->install_source);
// 	if (FAILED(hr)) {
// 		return hr;
// 	}
// 	// Validate install_source value.
// 	args_->install_source.MakeLower();
// 	if ((args_->install_source.Compare(kCmdLineInstallSource_OneClick) != 0) &&
// 		(args_->install_source.Compare(kCmdLineInstallSource_Update3Web) != 0)) {
// 			args_->install_source.Empty();
// 			return E_INVALIDARG;
// 	}

// 	args_->mode = COMMANDLINE_MODE_WEBPLUGIN;

// 	CString urldomain;
// 	hr = parser_->GetSwitchArgumentValue(kCmdLineWebPlugin,
// 		0,
// 		&urldomain);
// 	if (FAILED(hr)) {
// 		return hr;
// 	}
// 	hr = StringUnescape(urldomain, &args_->webplugin_urldomain);
// 	if (FAILED(hr)) {
// 		return hr;
// 	}
// 
// 	CString webplugin_args;
// 	hr = parser_->GetSwitchArgumentValue(kCmdLineWebPlugin,
// 		1,
// 		&webplugin_args);
// 	if (FAILED(hr)) {
// 		return hr;
// 	}
// 	return StringUnescape(webplugin_args, &args_->webplugin_args);]
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnCodeRed() {
// 	args_->mode = COMMANDLINE_MODE_CODE_RED_CHECK;
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnRecover() {
// 	args_->mode = COMMANDLINE_MODE_RECOVER;
	return parser_->GetSwitchArgumentValue(
		kCmdLineRecover,
		0,
		&args_->code_red_metainstaller_path);
}

HRESULT PCAgentCommandLineValidator::OnRecoverMachine() {
// 	args_->mode = COMMANDLINE_MODE_RECOVER;
	args_->is_machine_set = true;
	return parser_->GetSwitchArgumentValue(
		kCmdLineMachine,
		0,
		&args_->code_red_metainstaller_path);
}

HRESULT PCAgentCommandLineValidator::OnUninstall() {
// 	args_->mode = COMMANDLINE_MODE_UNINSTALL;
	return S_OK;
}

HRESULT PCAgentCommandLineValidator::OnRegisterProduct() {
// 	args_->mode = COMMANDLINE_MODE_REGISTER_PRODUCT;
	parser_->GetSwitchArgumentValue(kCmdLineInstallSource,
		0,
		&args_->install_source);
	return GetExtraAndAppArgs(kCmdLineRegisterProduct);
}

HRESULT PCAgentCommandLineValidator::OnUnregisterProduct() {
// 	args_->mode = COMMANDLINE_MODE_UNREGISTER_PRODUCT;
	return GetExtraAndAppArgs(kCmdLineUnregisterProduct);
}

HRESULT PCAgentCommandLineValidator::OnPing() {
// 	args_->mode = COMMANDLINE_MODE_PING;
	return parser_->GetSwitchArgumentValue(kCmdLinePing,
		0,
		&args_->ping_string);
}